/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package br.pucsp.projetoesp.logica;

import br.pucsp.projetoesp.modeloDeDominio.Dica;
import br.pucsp.projetoesp.modeloDeDominio.Casa;
import br.pucsp.projetoesp.modeloDeDominio.CasaBranca;
import br.pucsp.projetoesp.modeloDeDominio.CasaPreta;
import br.pucsp.projetoesp.modeloDeDominio.Preenchimento;
import br.pucsp.projetoesp.modeloDeDominio.Tabuleiro;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/**
 *
 * @author Ricardo
 */
public class TabuleiroFactory {

    int xPosAtual;
    int yPosAtual;

    public Tabuleiro create(List<Dica> dicas) {
        Tabuleiro tab = new Tabuleiro();
        Casa[][] casas = tab.getCasasDoTabuleiro();
        
        CasaBranca casaDica0 = new CasaBranca(new Preenchimento(dicas.get(0).getPalavraResposta().getPalavra().charAt(0) + ""), 1, 9);
        dicas.get(0).addObserver(casaDica0);
        colocarPalavraHorizontal(casaDica0, dicas.get(0).getPalavraResposta().getPalavra(), 0, casas, dicas.get(0));
        
        CasaBranca casaDica1 = new CasaBranca(new Preenchimento(dicas.get(1).getPalavraResposta().getPalavra().charAt(0) + ""),14,3);
        dicas.get(1).addObserver(casaDica1);
        colocarPalavraVertical(casaDica1, dicas.get(1).getPalavraResposta().getPalavra(), 1, casas, dicas.get(1));
        
        CasaBranca casaDica2 = new CasaBranca(new Preenchimento(dicas.get(2).getPalavraResposta().getPalavra().charAt(0) + ""),5,8);
        dicas.get(1).addObserver(casaDica2);
        colocarPalavraHorizontal(casaDica2, dicas.get(2).getPalavraResposta().getPalavra(), 2, casas, dicas.get(2));
        
        CasaBranca casaDica3 = new CasaBranca(new Preenchimento(dicas.get(3).getPalavraResposta().getPalavra().charAt(0) + ""),11,16);
        dicas.get(1).addObserver(casaDica3);
        colocarPalavraVertical(casaDica3, dicas.get(3).getPalavraResposta().getPalavra(), 3, casas, dicas.get(3));
        
        
        preencherCasasVazias(casas);

        return tab;
    }

    //Em construção
    public Tabuleiro createF(List<Dica> dicas) {
        Tabuleiro saida = new Tabuleiro();
        Casa[][] casas = saida.getCasasDoTabuleiro();
        List<String> respostas = obterRespostas(dicas);
        for (int i = 0; i < respostas.size(); i++) {
            String resposta = respostas.get(i);
            //Inicia na posicao 0/0
            Casa posicaoPonteiroDaFabrica = casas[0][0];
            xPosAtual = 0;
            yPosAtual = 0;
            while (posicaoPonteiroDaFabrica != null) {
                try {
                    posicaoPonteiroDaFabrica = andarUmaCasa(posicaoPonteiroDaFabrica, casas);

                } catch (RuntimeException ex) {
                    ex.printStackTrace();
                    break;
                }
            }
            if (cabeNaHorizontal(resposta, posicaoPonteiroDaFabrica, casas)) {
             //   colocarPalavraHorizontal(posicaoPonteiroDaFabrica, resposta, i, casas);
            } else {
                if (cabeNaVertical(resposta, posicaoPonteiroDaFabrica, casas)) {
                  //  colocarPalavraVertical(posicaoPonteiroDaFabrica, resposta, i, casas);
                }

            }

        }

        for (int i = 0; i < Tabuleiro.NUMERO_DE_CASAS_NA_HORIZONTAL; i++) {
            for (int j = 0; j < Tabuleiro.NUMERO_DE_CASAS_NA_VERTICAL; j++) {
                Casa casaDaPosicao = casas[i][j];
                if (casaDaPosicao == null) {
                    casas[i][j] = new CasaPreta(null, i, j);
                }
            }

        }

        return saida;
    }

    private void preencherCasasVazias(Casa[][] casas){
        for (int i = 0; i < Tabuleiro.NUMERO_DE_CASAS_NA_HORIZONTAL; i++) {
            for (int j = 0; j < Tabuleiro.NUMERO_DE_CASAS_NA_VERTICAL; j++) {
                Casa casaDaPosicao = casas[i][j];
                if (casaDaPosicao == null) {
                    casas[i][j] = new CasaPreta(null, i, j);
                }
            }

        }
    }

    private void colocarPalavraVertical(Casa posicao, String resposta, int NumeroDaDica, Casa[][] casas, Dica dica) {
        Preenchimento nDica = new Preenchimento("" + (NumeroDaDica + 1));

          int yDaPosicao = 0;
         int xDaPosicao = 0;
        if (posicao != null) {
            yDaPosicao = posicao.getPosicaoVertical();
            xDaPosicao = posicao.getPosicaoHorizontal();
        }else{
           yDaPosicao = yPosAtual;
           xDaPosicao = xPosAtual;
        }

        posicao = new CasaPreta(nDica, xDaPosicao, yDaPosicao);

        casas[xDaPosicao][yDaPosicao] = posicao;
        for (int i = 1; i <= resposta.length(); i++) {
            Preenchimento preenchimentoCasa = new Preenchimento("" + resposta.charAt(i - 1));
            casas[xDaPosicao][yDaPosicao + i] = new CasaBranca(preenchimentoCasa, xDaPosicao, xDaPosicao + 1);
            dica.addObserver((CasaBranca)casas[xDaPosicao][yDaPosicao + i]);
        }

    }

    private void colocarPalavraHorizontal(Casa posicao, String resposta, int NumeroDaDica, Casa[][] casas, Dica dica) {
        Preenchimento nDica = new Preenchimento("" + (NumeroDaDica + 1));

         int yDaPosicao = 0;
         int xDaPosicao = 0;
        if (posicao != null) {
            yDaPosicao = posicao.getPosicaoVertical();
            xDaPosicao = posicao.getPosicaoHorizontal();
        }else{
           yDaPosicao = yPosAtual;
           xDaPosicao = xPosAtual;
        }
        posicao = new CasaPreta(nDica, xDaPosicao, yDaPosicao);


        casas[xDaPosicao][yDaPosicao] = posicao;
        for (int i = 1; i <= resposta.length(); i++) {
            Preenchimento preenchimentoCasa = new Preenchimento("" + resposta.charAt(i - 1));
            casas[xDaPosicao + i][yDaPosicao] = new CasaBranca(preenchimentoCasa, xDaPosicao + i, yDaPosicao);
            dica.addObserver((CasaBranca)casas[xDaPosicao + i][yDaPosicao]);
        }

    }

    private boolean cabeNaHorizontal(String resposta, Casa posicao, Casa[][] casas) {
        int tamanhoResposta = resposta.length();
        int xDaPosicao = xPosAtual;
        int yDaPosicao = yPosAtual;
        //-2 pois começa da posicao 0 e pq precisa de 1 casa para colocar o número da dia
        if (xDaPosicao + tamanhoResposta < Tabuleiro.NUMERO_DE_CASAS_NA_HORIZONTAL - 1) {
            boolean casasEstaoVazias = true;
            for (int i = xDaPosicao; i < xDaPosicao + tamanhoResposta; i++) {
                Casa proximaCasa = casas[i][yDaPosicao];
                if (proximaCasa != null) {
                    casasEstaoVazias = false;
                    break;
                }
            }
            if (casasEstaoVazias) {
                return true;
            } else {
                return false;
            }

        } else {
            return false;
        }
    }

    private boolean cabeNaVertical(String resposta, Casa posicao, Casa[][] casas) {
        int tamanhoResposta = resposta.length();
        int xDaPosicao = xPosAtual;
        int yDaPosicao = yPosAtual;
        //-2 pois começa da posicao 0 e pq precisa de 1 casa para colocar o número da dia
        if (xDaPosicao + tamanhoResposta < Tabuleiro.NUMERO_DE_CASAS_NA_VERTICAL - 1) {
            boolean casasEstaoVazias = true;
            for (int i = yDaPosicao; i < yDaPosicao + tamanhoResposta; i++) {
                Casa proximaCasa = casas[i][yDaPosicao];
                if (proximaCasa != null) {
                    casasEstaoVazias = false;
                    break;
                }
            }
            if (casasEstaoVazias) {
                return true;
            } else {
                return false;
            }

        } else {
            return false;
        }
    }

    private List<String> obterRespostas(List<Dica> dicas) {
        List<String> saida = new ArrayList<String>();
        for (Dica dica : dicas) {
            saida.add(dica.getPalavraResposta().getPalavra());
        }
        return saida;
    }

    private Casa andarUmaCasa(Casa posicao, Casa[][] casas) {
        int xDaCasa = posicao.getPosicaoHorizontal();
        int yDaCasa = posicao.getPosicaoVertical();
        if (xDaCasa < Tabuleiro.NUMERO_DE_CASAS_NA_HORIZONTAL - 1) {
            xDaCasa++;
            xPosAtual++;
            return casas[xDaCasa][yDaCasa];
        } else if (yDaCasa < Tabuleiro.NUMERO_DE_CASAS_NA_VERTICAL - 1) {
            yDaCasa++;
            yPosAtual++;
            return casas[0][yDaCasa];
        } else {
            throw new RuntimeException();
        }
    }
}
